#pragma once

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <cerrno>

#define MODE 0666
#define PATH "./fifo"
#define SIZE 1024

class Fifo
{
public:
    Fifo(const std::string& path = PATH)
        : _path(path)
    {
        umask(0);
        int ret = mkfifo(_path.c_str(), MODE);
        if (ret == -1)
        {
            std::cerr << "mkfifo failed, errno: " << errno << ", errstring: " << strerror(errno) << std::endl;
            exit(1);
        }
        else
        {
            std::cout << "mkfifo success" << std::endl;
        }
    }

    ~Fifo()
    {
        int ret = unlink(_path.c_str());
        if (ret == -1)
        {
            std::cerr << "unlink failed, errno: " << errno << ", errstring: " << strerror(errno) << std::endl;
            exit(1);
        }
        else
        {
            std::cout << "unlink success" << std::endl;
        }
    }
    
private:
    std::string _path;  //路径 + 文件名  
};

//协同机制
class Sync
{
public:
    void open_write()
    {
        _wfd = open(PATH, O_WRONLY);
        if (_wfd == -1)
        {
            std::cerr << "open_write failed, errno: " << errno << ", errstring: " << strerror(errno) << std::endl;
            exit(1);
        }
    }

    void open_read()
    {
        _rfd = open(PATH, O_RDONLY);
        if (_rfd == -1)
        {
            std::cerr << "open_read failed, errno: " << errno << ", errstring: " << strerror(errno) << std::endl;
            exit(1);
        }
    }

    //服务端用来等待的函数
    bool Wait()
    {
        uint32_t c;
        int n = read(_rfd, &c, sizeof(uint32_t));
        if (n == sizeof(uint32_t))
        {
            return true;
        }
        else if (n == 0)
        {
            return false;
        }
        else
        {
            std::cerr << "Wait failed, errno: " << errno << ", errstring: " << strerror(errno) << std::endl;
            exit(1);
        }
    }

    //客户端用来叫醒服务端
    void wakeup()
    {
        uint32_t c;
        int n = write(_wfd, &c, sizeof(uint32_t));
        if (n != sizeof(uint32_t))
        {
            std::cerr << "wakeup failed, errno: " << errno << ", errstring: " << strerror(errno) << std::endl;
            exit(1);
        }
    }
private:
    int _wfd = -1;
    int _rfd = -1;
};